package com.charlotte.study.gupao.template.jdbc;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author junjie.ding
 * @date 2020/3/13
 */
public abstract class JdbcTemplate {

    private DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public final List<?> execute(String sql, Object[] values, RowMapper<?> rowMapper) throws Exception {
        // 获取连接
        Connection connection = this.getConnection();

        // 创建语句集
        PreparedStatement statement = this.createPreparedStatement(connection, sql);

        // 执行语句集
        ResultSet resultSet = this.executeSql(statement, values);
        
        // 处理结果集
        List<Object> objects = this.parseResultSet(resultSet, rowMapper);

        // 关闭结果集
        resultSet.close();

        // 关闭语句集
        statement.close();

        // 关闭连接
        connection.close();

        return objects;
    }

    private List<Object> parseResultSet(ResultSet resultSet, RowMapper<?> rowMapper) throws Exception {
        List<Object> result = new ArrayList<>();
        int rownum = 0;
        while (resultSet.next()){
            result.add(rowMapper.mapRow(resultSet, rownum++));
        }
        return result;
    }

    private ResultSet executeSql(PreparedStatement statement, Object[] values) throws SQLException {
        for (int i = 0; i < values.length; i++) {
            statement.setObject(i, values[i]);
        }
        return statement.executeQuery();
    }

    private PreparedStatement createPreparedStatement(Connection connection, String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    private Connection getConnection() throws SQLException {
        return this.dataSource.getConnection();
    }
}
